﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SD.LLBLGen.Pro.ORMSupportClasses;
using System.Windows.Forms;
using WHMS.HelperClasses;
using System.Data;
using WHMS.FactoryClasses;
using WHMS;
using System.Drawing;
using WHMS.EntityClasses;
using System.Data.SqlClient;

namespace WMS.HelperClasses
{
	public class DataMngrFormBase<TEntity> : IDisposable where TEntity : EntityBase2, IEntity2
	{
		#region properties
		IEntityCollection2 _collection;		
		DataGridView _dataGrid;
		BindingSource _bindingSource;
		Button _saveBtn;
		Label _saveResult;
		Label _deleteResult;
		RelationPredicateBucket _filter;
		PrefetchPath2 _prefetchPath;

		EntityField2 _pkField; 
		EntityField2 _valueMember; 
		EntityField2 _displayMember; 
		EntityField2 _joinedField; 
		EntityField2 _filterField;
		ListBox _allMNList;
		ListBox _assignedMNList;
		DataTable _allMNDataSource;
		DataTable _assignedMNDataSource;
		Button _assignSelectedBtn;
		Button _assignAllBtn;
		Button _unAssignSelectedBtn;
		Button _unAssignAllBtn;
		Button _saveMNAssociationBtn;
        Button _nextPageBtn;
        Button _prevPageBtn;
		Type _mnEntityType;
		bool _mnRelationSet;
		bool _mnRelationSButtonsSet;
        int _totalrecords;

        bool _allowPaging;//Diab - attribute to set paging
        int _pageSize;//Diab -page size in case of paging
		int _currentRowIndex = 0;
        int _currentPageIndex = 1;
		List<int> _mandatoryColumnsIndexes;
		List<int> _numericColumnsIndexes;
		List<int> _comboboxColumnsIndexes;
		Dictionary<int, EntityField2> _uniqueFields;
		short _decimalPlaces;
		int _itemColumnIndex;
		int _quantityColumnIndex;
		#endregion

		#region events

		public delegate void RaiseRowValidating(int rowIndex, ref bool hasErrors);
		public event RaiseRowValidating RowValidating;

		public delegate void RaiseComboboxColumnSelectionChanged(object selectedValue);
		public event RaiseComboboxColumnSelectionChanged ComboboxColumnSelectionChanged;

		public delegate void RaiseSelectionChanged(int selectedRowIndex);
		public event RaiseSelectionChanged SelectionChanged;

		public delegate void RaiseMNSaved(int selectedId);
		public event RaiseMNSaved MNSaved;

		public delegate void RaiseBeforeSave(IEntityCollection2 collectionToBeSaved);
		public event RaiseBeforeSave BeforeSave;

		public delegate void RaiseAfterSave();
		public event RaiseAfterSave AfterSave;

		#endregion

		#region CTors
		public DataMngrFormBase(IEntityCollection2 collection, DataGridView datagrid, BindingSource bindingSource, Button saveBtn, Label saveResult, Label deleteResult)
			:this(collection, datagrid,  bindingSource, saveBtn, saveResult, deleteResult, null)
		{
		}
		public DataMngrFormBase(IEntityCollection2 collection, DataGridView datagrid, BindingSource bindingSource, Button saveBtn, Label saveResult, Label deleteResult, RelationPredicateBucket filter)
			: this(collection, datagrid, bindingSource, saveBtn, saveResult, deleteResult, filter, null)
		{
		}
		public DataMngrFormBase(IEntityCollection2 collection, DataGridView datagrid, BindingSource bindingSource, Button saveBtn, Label saveResult, Label deleteResult, RelationPredicateBucket filter, PrefetchPath2 prefetch)
		{
			_itemColumnIndex = -1; 
			_quantityColumnIndex = -1;

			_decimalPlaces = 2;
			_filter = filter;
			_prefetchPath = prefetch;
			_collection = collection;

			_dataGrid = datagrid;
			_bindingSource = bindingSource;
			_saveBtn = saveBtn;
			_saveResult = saveResult;
			_deleteResult = deleteResult;

			_mandatoryColumnsIndexes = new List<int>();

			_dataGrid.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(_dataGrid_DataBindingComplete);
			_dataGrid.CellEndEdit += new DataGridViewCellEventHandler(_dataGrid_CellEndEdit);
			_dataGrid.RowValidating += new DataGridViewCellCancelEventHandler(_dataGrid_RowValidating);
			_dataGrid.DataError += new DataGridViewDataErrorEventHandler(_dataGrid_DataError);
			_dataGrid.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(_dataGrid_EditingControlShowing);
			_bindingSource.CurrentChanged += new EventHandler(_bindingSource_CurrentChanged);
			_saveBtn.Click += new EventHandler(_saveBtn_Click);

			_dataGrid.SelectionChanged += new EventHandler(_dataGrid_SelectionChanged);
			_dataGrid.RowEnter += new DataGridViewCellEventHandler(_dataGrid_RowEnter);
			_dataGrid.CellEnter += new DataGridViewCellEventHandler(_dataGrid_CellEnter);
			_dataGrid.CellDoubleClick += new DataGridViewCellEventHandler(_dataGrid_CellDoubleClick);

			LoadEntities();
		}

        public DataMngrFormBase(IEntityCollection2 collection, DataGridView datagrid, BindingSource bindingSource, Button saveBtn, Label saveResult, Label deleteResult, RelationPredicateBucket filter, PrefetchPath2 prefetch, bool allowPaging, Button nextPageBtn, Button prevPageBtn)//Diab - to allow paging
        {
            _pageSize = 100;//Diab
            _allowPaging = allowPaging;//Diab
            _itemColumnIndex = -1;
            _quantityColumnIndex = -1;


            _decimalPlaces = 2;
            _filter = filter;
            _prefetchPath = prefetch;
            _collection = collection;

            _dataGrid = datagrid;
            _bindingSource = bindingSource;
            _saveBtn = saveBtn;
            _saveResult = saveResult;
            _deleteResult = deleteResult;
            _nextPageBtn = nextPageBtn;
            _prevPageBtn = prevPageBtn;

            _mandatoryColumnsIndexes = new List<int>();

            _totalrecords = DALHelper.GetCount(_collection, _filter);
            _dataGrid.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(_dataGrid_DataBindingComplete);
            _dataGrid.CellEndEdit += new DataGridViewCellEventHandler(_dataGrid_CellEndEdit);
            _dataGrid.RowValidating += new DataGridViewCellCancelEventHandler(_dataGrid_RowValidating);
            _dataGrid.DataError += new DataGridViewDataErrorEventHandler(_dataGrid_DataError);
            _dataGrid.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(_dataGrid_EditingControlShowing);
            _bindingSource.CurrentChanged += new EventHandler(_bindingSource_CurrentChanged);
            _saveBtn.Click += new EventHandler(_saveBtn_Click);
            _nextPageBtn.Click += new EventHandler(NextPageBtn_Click);//Diab - Event handler for Nextpage in case of paging enabled
            _prevPageBtn.Click += new EventHandler(PrevPageBtn_Click);//Diab - Event handler for Prevpage in case of paging enabled

            _dataGrid.SelectionChanged += new EventHandler(_dataGrid_SelectionChanged);
            _dataGrid.RowEnter += new DataGridViewCellEventHandler(_dataGrid_RowEnter);
            _dataGrid.CellEnter += new DataGridViewCellEventHandler(_dataGrid_CellEnter);
            _dataGrid.CellDoubleClick += new DataGridViewCellEventHandler(_dataGrid_CellDoubleClick);



            LoadEntities();
        }
		#endregion

		public void SetUniqueFields(Dictionary<int, EntityField2> uniqueFields, EntityField2 pkField)
		{
			_uniqueFields = uniqueFields;
			_pkField = pkField;
		}
		public void SetMandatoryFields(List<int> columnsIndexes)
		{
			_mandatoryColumnsIndexes = columnsIndexes;
		}
		public void SetNumericFields(List<int> columnsIndexes)
		{
			_numericColumnsIndexes = columnsIndexes;
		}
		public void SetDecimalPlaces(short decimalPlaces)
		{
			_decimalPlaces = decimalPlaces;
		}
		public void SetQuantityAndItemColumnIndexes(int itemIndex, int quantityIndex)
		{
			_itemColumnIndex = itemIndex;
			_quantityColumnIndex = quantityIndex;
		}

		public void RaiseSelectedChangedEventForComboBoxColumns(List<int> columnsIndexes)
		{
			_comboboxColumnsIndexes = columnsIndexes;
		}
		public void ValidateCollection()
		{
			var invalidEntities = new EntityCollection<EntityBase2>();

			for (int index = 0; index < _collection.Count; index++)
			{
				if (index >= _dataGrid.Rows.Count)
					break;

				if (string.IsNullOrEmpty(_dataGrid.Rows[index].ErrorText.Trim()))
				{
					if (_collection[index].IsDirty == false && _collection[index].IsNew == true)
						invalidEntities.Add((EntityBase2)_collection[index]);

					continue;
				}

				_collection[index].IsDirty = false;

				if (_collection[index].IsDirty == false && _collection[index].IsNew == true)
					invalidEntities.Add((EntityBase2)_collection[index]);
			}

			foreach (var entity in invalidEntities)
			{
				_collection.Remove(entity);
			}
		}
		public bool ValidateCollectionEx()
		{
			var valid = true;

			var invalidEntities = new EntityCollection<EntityBase2>();

			for (int index = 0; index < _collection.Count; index++)
			{
				if (index >= _dataGrid.Rows.Count)
					break;

				if (string.IsNullOrEmpty(_dataGrid.Rows[index].ErrorText.Trim()))
				{
					if (_collection[index].IsDirty == false && _collection[index].IsNew == true)
						invalidEntities.Add((EntityBase2)_collection[index]);

					continue;
				}

				valid = false;
			}

			foreach (var entity in invalidEntities)
			{
				_collection.Remove(entity);
			}

			return valid;
		}

		public bool IsDataValid()
		{
			for (int index = 0; index < _collection.Count; index++)
			{
				if (index >= _dataGrid.Rows.Count)
					break;

				if (string.IsNullOrEmpty(_dataGrid.Rows[index].ErrorText.Trim()))
				{
					continue;
				}

				return false;
			}

			return true;			
		}

		#region Grid events
		void _dataGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
		{
			if (_itemColumnIndex < 0 || _quantityColumnIndex < 0)
				return;

			if (e.ColumnIndex != _quantityColumnIndex)
				return;

			var itemIdValue = _dataGrid.Rows[e.RowIndex].Cells[_itemColumnIndex].Value;
			if (itemIdValue == null)
				return;

			var form = new UnitConverterForm((int)itemIdValue);
			if (form.ShowDialog() == DialogResult.OK)
			{
				_dataGrid.SuspendLayout();
				_dataGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = form.Value;
				_dataGrid.UpdateCellValue(e.ColumnIndex, e.RowIndex);
				_dataGrid.ResumeLayout(true);
			}

		}

		void _dataGrid_CellEnter(object sender, DataGridViewCellEventArgs e)
		{
			//throw new NotImplementedException();
		}
		void _dataGrid_RowEnter(object sender, DataGridViewCellEventArgs e)
		{
			if (_dataGrid.SelectedCells.Count <= 0)
				return;

			if (e.RowIndex == _currentRowIndex)
			{
				if (_dataGrid.RowCount - _currentRowIndex == 1)
				{
					_dataGrid.Rows[_currentRowIndex].ErrorText = String.Empty;
					foreach (var index in _mandatoryColumnsIndexes)
					{
						_dataGrid.Rows[_currentRowIndex].Cells[index].ErrorText = string.Empty;
					}
				}
				return;
			}

			_currentRowIndex = e.RowIndex;

			EnableDisableMNButtons();
			OnSelectionChanged();
		}
		void _dataGrid_SelectionChanged(object sender, EventArgs e)
		{
			//throw new NotImplementedException();
		}
		void _dataGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
		{
			var columnIndex = (int)(((System.Windows.Forms.DataGridView)(sender)).CurrentCell.ColumnIndex);

			if (e.Control is ComboBox)
			{
				if (_comboboxColumnsIndexes != null)
				{
					ComboBox comboBox = e.Control as ComboBox;
					comboBox.SelectionChangeCommitted -= new EventHandler(comboBox_SelectionChangeCommitted);
					if (_comboboxColumnsIndexes.Contains(columnIndex))
					{
						comboBox.SelectionChangeCommitted += new EventHandler(comboBox_SelectionChangeCommitted);
					}
				}
			}

			if (_numericColumnsIndexes == null)
				return;			

			e.Control.KeyPress -= new System.Windows.Forms.KeyPressEventHandler(this.TextboxNumeric_KeyPress);
			if (_numericColumnsIndexes.Contains(columnIndex))
			{
				e.Control.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextboxNumeric_KeyPress);
			}
		}

		void OnRowValidating(int rowIndex, ref bool hasErrors)
		{
			if (RowValidating != null)
			{
				RowValidating(rowIndex, ref hasErrors);
			}
		}

		void comboBox_SelectionChangeCommitted(object sender, EventArgs e)
		{
			if (ComboboxColumnSelectionChanged != null)
			{
				ComboBox combo = sender as ComboBox;

				if (combo.SelectedValue == null)
					return;

				int selectedId = (int)combo.SelectedValue;
				ComboboxColumnSelectionChanged(selectedId);
			}
		}
		void _dataGrid_DataError(object sender, DataGridViewDataErrorEventArgs e)
		{
			// DO NOTHING.
			// This empty handler solves a problem in case of displaying a new empty row with a null valiue for the ItemId column
			// associated with a dropdownList.
		}
		void _dataGrid_RowValidating(object sender, DataGridViewCellCancelEventArgs e)
		{
			ValidateRow(e.RowIndex);
		}

		private void ValidateRow(int rowIndex)
		{
			var hasErrors = false;
			if (_mandatoryColumnsIndexes == null)
				return;

			foreach (var index in _mandatoryColumnsIndexes)
			{
				var cellValue = _dataGrid.Rows[rowIndex].Cells[index].Value;

				if (cellValue == null
					|| string.IsNullOrEmpty(cellValue.ToString().Trim())
					|| (cellValue is int && ((int)cellValue) == 0)
					|| (cellValue is decimal && ((decimal)cellValue) == 0)
					)
				{
					_dataGrid.Rows[rowIndex].Cells[index].ErrorText = "يجب إدخال قيمة";
					hasErrors = true;
					continue;
				}

				if (_uniqueFields != null)
				{
					EntityField2 entityField;
					if (_uniqueFields.TryGetValue(index, out entityField))
					{
						int id = 0;
						GetId(rowIndex, out id);
						if (CheckExistingValue(entityField, cellValue.ToString()))//DALHelper.CheckExistingValue(entityField, cellValue.ToString(), _pkField, id))
						{
							_dataGrid.Rows[rowIndex].Cells[index].ErrorText = "القيمة المدخلة مستخدمة مسبقا";
							//_dataGrid.Rows[e.RowIndex].ErrorText = "يوجد أخطاء فى إدخال البيانات";
							hasErrors = true;
							continue;
						}
					}
				}

				_dataGrid.Rows[rowIndex].Cells[index].ErrorText = string.Empty;
				continue;
			}

			OnRowValidating(rowIndex, ref hasErrors);

			if (!hasErrors)
			{
				_dataGrid.Rows[rowIndex].ErrorText = string.Empty;
			}
			else
			{
				_dataGrid.Rows[rowIndex].ErrorText = "يوجد أخطاء فى إدخال البيانات";


				if (_collection.Count > rowIndex)
				{
					_collection[rowIndex].IsDirty = false;
				}
			}
		}

		bool CheckExistingValue(EntityField2 entityField, string valueTocheck)
		{
			if (_collection.FindMatches(new PredicateExpression(entityField == valueTocheck)).Count > 1)
				return true;

			return false;
		}

		void _dataGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
		{
			// Clear the row error in case the user presses ESC.   
			//_dataGrid.Rows[e.RowIndex].ErrorText = String.Empty;
		}

		void _dataGrid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
		{
			if(e.ListChangedType == System.ComponentModel.ListChangedType.Reset)
				SelectFirstRow();
		}
		#endregion
		
		#region Manage M:N data
		public void SetMNInfo(Type mnEntityType, ListBox allMNList, ListBox assignedMNList, EntityField2 valueMember, EntityField2 displayMember, EntityField2 joinedField, EntityField2 filterField)
		{
			_mnEntityType = mnEntityType;
			_allMNList = allMNList;
			_assignedMNList = assignedMNList;
			_valueMember = valueMember;
			_displayMember = displayMember;
			_joinedField = joinedField;
			_filterField = filterField;
			_mnRelationSet = true;
		}
		public void SetMNAssociationButtons(Button assignSelectedBtn, Button assignAllBtn, Button unAssignSelectedBtn, Button unAssignAllBtn, Button saveMNAssociationBtn)
		{
			_assignSelectedBtn = assignSelectedBtn;
			_assignAllBtn = assignAllBtn;
			_unAssignSelectedBtn = unAssignSelectedBtn;
			_unAssignAllBtn = unAssignAllBtn;
			_saveMNAssociationBtn = saveMNAssociationBtn;
			_mnRelationSButtonsSet = true;

			_assignSelectedBtn.Click += new EventHandler(assignSelectedBtn_Click);
			_assignAllBtn.Click += new EventHandler(assignAllBtn_Click);
			_unAssignSelectedBtn.Click += new EventHandler(unAssignSelectedBtn_Click);
			_unAssignAllBtn.Click += new EventHandler(unAssignAllBtn_Click);
			_saveMNAssociationBtn.Click += new EventHandler(saveMNAssociationBtn_Click);
		}
		private void GetMNData()
		{
			if (!_mnRelationSet || _currentRowIndex < 0 || _dataGrid.Rows.Count <= 1)
				return;

			int id = 0;			
			GetId(out id);

			_allMNDataSource = DALHelper.GetMNUnrelatedItems(_valueMember, _displayMember, _joinedField, _filterField, id);
			_allMNList.DataSource = _allMNDataSource;
			_allMNList.DisplayMember = _displayMember.Name;
			_allMNList.ValueMember = _valueMember.Name;

			_assignedMNDataSource = DALHelper.GetMNRelatedItems(_valueMember, _displayMember, _joinedField, _filterField, id);
			_assignedMNList.DataSource = _assignedMNDataSource;
			_assignedMNList.DisplayMember = _displayMember.Name;
			_assignedMNList.ValueMember = _valueMember.Name;

			DataColumn[] keyColumn1 = new DataColumn[1];
			keyColumn1[0] = _allMNDataSource.Columns["Id"];
			_allMNDataSource.PrimaryKey = keyColumn1;

			DataColumn[] keyColumn2 = new DataColumn[1];
			keyColumn2[0] = _assignedMNDataSource.Columns["Id"];
			_assignedMNDataSource.PrimaryKey = keyColumn2;

		}
		void saveMNAssociationBtn_Click(object sender, EventArgs e)
		{
			if (_dataGrid.SelectedCells.Count <= 0)
				return;

			int id;
			if (!GetId(out id))
				return;

			var entityType = (EntityType)Enum.Parse(typeof(EntityType), _mnEntityType.Name, false);
			var myEntity = GeneralEntityFactory.Create(entityType);
			var entityfactory = myEntity.GetEntityFactory();
			var collection = entityfactory.CreateEntityCollection();

			foreach (DataRow row in _assignedMNDataSource.Rows)
			{
				var entity = GeneralEntityFactory.Create(entityType);
				entity.Fields[_filterField.Name].CurrentValue = id;
				entity.Fields[_filterField.Name].IsChanged = true;

				entity.Fields[_joinedField.Name].CurrentValue = int.Parse(row["Id"].ToString());
				entity.Fields[_joinedField.Name].IsChanged = true;
				entity.IsDirty = true;

				collection.Add(entity);
			}

			DALHelper.SaveMNAssociationEntities(_mnEntityType, collection, _filterField, id);

			OnMNSaved(id);
		}
		protected void OnMNSaved(int id)
		{
			if (MNSaved != null)
			{
				MNSaved(id);
			}
		}
		void unAssignAllBtn_Click(object sender, EventArgs e)
		{
			foreach (DataRow row in _assignedMNDataSource.Rows)
			{
				_allMNDataSource.ImportRow(row);
			}

			_assignedMNDataSource.Rows.Clear();
		}
		void unAssignSelectedBtn_Click(object sender, EventArgs e)
		{
			MoveRowsBeweenDataTables(_assignedMNDataSource, _allMNDataSource, (x)=>_assignedMNList.GetSelected(x), "Id");
		}
		private void MoveRowsBeweenDataTables(DataTable source, DataTable target, Func<int, bool> filter, string PKName)
		{
			var PKs = new List<int>();

			for (int index = 0; index < source.Rows.Count; index++)
			{
				DataRow row = source.Rows[index];

				if (filter(index))
				{
					target.ImportRow(row);
					PKs.Add(int.Parse(row[PKName].ToString()));
				}
			}

			foreach (var PK in PKs)
			{
				var dr = source.Rows.Find(PK);
				if (dr != null)
				{
					source.Rows.Remove(dr);
				}
			}
		}
		void assignAllBtn_Click(object sender, EventArgs e)
		{
			foreach (DataRow row in _allMNDataSource.Rows)
			{
				_assignedMNDataSource.ImportRow(row);
			}

			_allMNDataSource.Rows.Clear();
		}
		void assignSelectedBtn_Click(object sender, EventArgs e)
		{
			MoveRowsBeweenDataTables(_allMNDataSource, _assignedMNDataSource, (x) => _allMNList.GetSelected(x), "Id");
		}
		private void EnableDisableMNButtons()
		{
			if (_mnRelationSButtonsSet)
			{
				int id;
				GetId(out id);
				if (id <= 0)
				{
					EnableDisableMNButtons(false);
					return;
				}

				EnableDisableMNButtons(true);
			}
		}
		private void EnableDisableMNButtons(bool enable)
		{
			if (_assignSelectedBtn != null)
				_assignSelectedBtn.Enabled = enable;
			if (_assignAllBtn != null)
				_assignAllBtn.Enabled = enable;
			if (_unAssignSelectedBtn != null)
				_unAssignSelectedBtn.Enabled = enable;
			if (_unAssignAllBtn != null)
				_unAssignAllBtn.Enabled = enable;
			if (_saveMNAssociationBtn != null)
				_saveMNAssociationBtn.Enabled = enable;
			if (_allMNList != null)
				_allMNList.Enabled = enable;
			if (_assignedMNList != null)
				_assignedMNList.Enabled = enable;
		}

		#endregion

		void LoadEntities()
		{
            //_collection.Clear();

            //DALHelper.FetchCollection(_collection, _filter, _prefetchPath);

            //_collection.RemovedEntitiesTracker = new EntityCollection<TEntity>();

            _totalrecords = DALHelper.GetCount(_collection, _filter);

            _collection.Clear();

            if (_allowPaging == false)
                DALHelper.FetchCollection(_collection, _filter, _prefetchPath);
            else
            {

                DALHelper.FetchCollection(_collection, _filter, _prefetchPath,_currentPageIndex,_pageSize);

                if (_currentPageIndex == 1) //First page therefore disable previous button 
                    _prevPageBtn.Enabled = false;
                else
                    _prevPageBtn.Enabled = true;


                if (Math.Ceiling((decimal)_totalrecords / _pageSize) == _currentPageIndex || _totalrecords <= _pageSize)//last page therefore disable next page button
                    _nextPageBtn.Enabled = false;
                else
                    _nextPageBtn.Enabled = true;
            }
            _collection.RemovedEntitiesTracker = new EntityCollection<TEntity>();

		}

		private void TextboxNumeric_KeyPress(object sender, KeyPressEventArgs e)
		{
			//bool valid = true;

			//if ((e.KeyChar >= 48 && e.KeyChar <= 57) || e.KeyChar == 8)
			//{
			//    valid = false;
			//}

			//e.Handled = valid;

			//e.Handled = !FormsHelper.IsNumericCharachter(e.KeyChar);
			FormsHelper.HandleNumericTextBoxKeypress(sender, e, _decimalPlaces);
		}
		protected void OnSelectionChanged()
		{
			if (SelectionChanged != null)
			{
				SelectionChanged(_currentRowIndex);
			}

			GetMNData();
		}

		protected void OnBeforeSave(IEntityCollection2 collectionToBeSaved)
		{
			if (BeforeSave != null)
			{
				//var filter = new PredicateExpression(new EntityProperty("IsDirty") == true);
				//filter.AddWithOr(new EntityProperty("IsNew") == false);

				//EntityView2<TEntity> entities = new EntityView2<TEntity>((EntityCollection<TEntity>)collectionToBeSaved.DefaultView, filter);

				//BeforeSave(entities);
				//var dirtyEntities = new EntityCollection<TEntity>();
				//foreach (TEntity entity in collectionToBeSaved)
				//{
				//    if (entity.IsDirty || !entity.IsNew)
				//        dirtyEntities.Add(entity);
				//}
				//BeforeSave(dirtyEntities);
				BeforeSave(collectionToBeSaved);
			}
		}
		protected void OnAfterSave()
		{
			if (AfterSave != null)
			{
				AfterSave();
			}
		}

		void SelectFirstRow()
		{
			if (_collection.Count <= 0)
				return;

			_currentRowIndex = 0;

			OnSelectionChanged();
		}

		void _saveBtn_Click(object sender, EventArgs e)
		{
			//ValidateCollection();
			ValidateData();

			if (!ValidateCollectionEx())
				return;

			OnBeforeSave(_collection);

			int saveResult = 0;
			int deleteResult = 0;

			try
			{
				saveResult = DALHelper.SaveCollection(_collection);
				deleteResult = DALHelper.DeleteCollection(_collection.RemovedEntitiesTracker);
                MessageBox.Show("تم الحفظ");
			}
			catch (Exception ex)
			{
				if (ex is ORMQueryExecutionException)
				{
					if (ex.InnerException is SqlException)
					{
						if (((SqlException)(ex.InnerException)).Errors[0].Number == 547)
						{
							var errorMsg = "لا يمكن إتمام عملية الحذف" + Environment.NewLine + "البيانات المراد خذفها متداخلة فى عمليات داخل النظام";
							MessageBox.Show(errorMsg, "خطأ فى عملية الحذف", MessageBoxButtons.OK, MessageBoxIcon.Error);
						}
					}				
				}
			}

			SetLabels(saveResult, deleteResult);

			OnAfterSave();

			LoadEntities();			
		}

        void PrevPageBtn_Click(object sender, EventArgs e)//Diab
        {
            if (_currentPageIndex > 1)
                _currentPageIndex--;
            LoadEntities();
        }

        void NextPageBtn_Click(object sender, EventArgs e)//Diab
        {
            _currentPageIndex++;
            LoadEntities();
        }

		public void ValidateData()
		{
			foreach (DataGridViewRow row in _dataGrid.Rows)
			{
				ValidateRow(row.Index);
			}
		}		

		void SetLabels(int saveResult, int deleteResult)
		{
			_saveResult.Text = saveResult.ToString();
			_deleteResult.Text = deleteResult.ToString();

			//if (saveResult > 0)
			//{
			//    _saveResult.ForeColor = Color.Blue;
			//}
			//else 
			//{
			//    _saveResult.ForeColor = Color.Black;
			//}

			//if (deleteResult > 0)
			//{
			//    _deleteResult.ForeColor = Color.Blue;
			//}
			//else
			//{
			//    _deleteResult.ForeColor = Color.Black;
			//}

		}

		void _bindingSource_CurrentChanged(object sender, EventArgs e)
		{
			//if (_dataGrid.SelectedCells.Count <= 0)
			//    return;

			//if (_dataGrid.SelectedCells[0].RowIndex == _currentRowIndex)
			//{
			//    if (_dataGrid.RowCount - _currentRowIndex == 1)
			//    {
			//        _dataGrid.Rows[_currentRowIndex].ErrorText = String.Empty;
			//        foreach (var index in _mandatoryColumnsIndexes)
			//        {
			//            _dataGrid.Rows[_currentRowIndex].Cells[index].ErrorText = string.Empty;
			//        }
			//    }
			//    return;
			//}

			//_currentRowIndex = _dataGrid.SelectedCells[0].RowIndex;

			//EnableDisableMNButtons();
			//OnSelectionChanged();
		}

		public bool GetId(out int id)
		{
			return GetId(_currentRowIndex, out id);
		}
		private bool GetId(int rowIndex, out int id)
		{
			id = 0;
			// Id Columns is assumed to be the last column in the grid.
			var value = _dataGrid.Rows[rowIndex].Cells[_dataGrid.Columns.Count - 1].Value;
			if (value == null)
				return false;

			return int.TryParse(value.ToString(), out id);
		}

		#region IDisposable implementation
		private bool _disposed = false;

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if(!this._disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if(disposing)
                {
					_dataGrid.DataBindingComplete -= _dataGrid_DataBindingComplete;
					_dataGrid.CellEndEdit -= _dataGrid_CellEndEdit;
					_dataGrid.RowValidating -= _dataGrid_RowValidating;
					_dataGrid.DataError -= _dataGrid_DataError;
					_dataGrid.EditingControlShowing -= _dataGrid_EditingControlShowing;
					_bindingSource.CurrentChanged -= _bindingSource_CurrentChanged;
					_saveBtn.Click -= _saveBtn_Click;

					if (_assignSelectedBtn != null)
						_assignSelectedBtn.Click -= assignSelectedBtn_Click;
					if (_assignAllBtn != null)
						_assignAllBtn.Click -= assignAllBtn_Click;
					if (_unAssignSelectedBtn != null)
						_unAssignSelectedBtn.Click -= unAssignSelectedBtn_Click;
					if (_unAssignAllBtn != null)
						_unAssignAllBtn.Click -= unAssignAllBtn_Click;
					if (_saveMNAssociationBtn != null)
						_saveMNAssociationBtn.Click -= saveMNAssociationBtn_Click;                    
                }

                // Note disposing has been done.
                _disposed = true;

            }
        }

        // Use C# destructor syntax for finalization code.
        // This destructor will run only if the Dispose method
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide destructors in types derived from this class.
        ~DataMngrFormBase()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
		}
		#endregion
	}
}
